using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace stsdev
{

    public enum SourceFileTypeEnum : int
    {
        None,
        Compile,
        Content,
        EmbeddedResource
    }

    public class ProjectFileBuilder
    {

        private static List<string> Folders = new List<string>();
        public static void AddFolder(string FolderName)
        {
            Folders.Add(FolderName);
        }

        private struct SourceFile
        {
            public string FileName;
            public SourceFileTypeEnum Type;
            public string CustomTool; //Added 2/7/08 DMANN to support CustomTool attribute
            public string DepedencyFileName; //Added 4/29/08 TPattison to support component designer
            public bool IsComponent; //Added 4/29/08 TPattison to support component designer
        }

        private static List<SourceFile> SourceFiles = new List<SourceFile>();

        public static void AddSourceFile(string FileName)
        {
            AddSourceFile(FileName, SourceFileTypeEnum.Compile);
        }

        //Added 2/7/08 DMANN to support CustomTool attribute
        public static void AddSourceFile(string FileName, SourceFileTypeEnum SourceFileType, string CustomTool)
        {
            SourceFile sourceFile;
            sourceFile.FileName = FileName;
            sourceFile.Type = SourceFileType;
            sourceFile.CustomTool = CustomTool;
            sourceFile.DepedencyFileName = null;
            sourceFile.IsComponent = false;
            SourceFiles.Add(sourceFile);
        }

        public static void AddSourceFile(string FileName, string DepedencyFileName, SourceFileTypeEnum SourceFileType)
        {
            SourceFile sourceFile;
            sourceFile.FileName = FileName;
            sourceFile.DepedencyFileName = DepedencyFileName;
            sourceFile.Type = SourceFileType;
            sourceFile.CustomTool = null;
            sourceFile.IsComponent = false;
            SourceFiles.Add(sourceFile);
        }

        public static void AddSourceFile(string FileName, SourceFileTypeEnum SourceFileType)
        {
            SourceFile sourceFile;
            sourceFile.FileName = FileName;
            sourceFile.DepedencyFileName = null;
            sourceFile.Type = SourceFileType;
            sourceFile.CustomTool = null; //Added 2/7/08 DMANN to support CustomTool attribute
            sourceFile.IsComponent = false;
            SourceFiles.Add(sourceFile);
        }

        public static void AddSourceFile(string FileName, SourceFileTypeEnum SourceFileType, bool IsComponent)
        {
            SourceFile sourceFile;
            sourceFile.FileName = FileName;
            sourceFile.DepedencyFileName = null;
            sourceFile.Type = SourceFileType;
            sourceFile.CustomTool = null; //Added 2/7/08 DMANN to support CustomTool attribute
            sourceFile.IsComponent = IsComponent;
            SourceFiles.Add(sourceFile);
        }

        private const string nsSP = "http://schemas.microsoft.com/developer/msbuild/2003";

        public static void Create(string ProjectName, string ProjectGuid)
        {

            StreamWriter manifestStream = new StreamWriter(ProjectName + ".csproj");
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = Encoding.UTF8;
            settings.Indent = true;
            settings.NewLineOnAttributes = false;
            settings.NewLineHandling = NewLineHandling.None;
            XmlWriter writer = XmlWriter.Create(manifestStream, settings);
            writer.WriteStartDocument();

            writer.WriteComment("Created by STSDEV at " + DateTime.Now.ToString());

            // <Project>
            writer.WriteStartElement("Project", nsSP);
            if (SolutionBuilder.SolutionVersionType == SolutionVersionTypeEnum.VS2008_30 ||
                SolutionBuilder.SolutionVersionType == SolutionVersionTypeEnum.VS2008_35)
            {
                writer.WriteAttributeString("ToolsVersion", "3.5");
            }
            writer.WriteAttributeString("DefaultTargets", "Build");

            // <PropertyGroup>
            writer.WriteStartElement("PropertyGroup");

            writer.WriteStartElement("Configuration");
            writer.WriteAttributeString("Condition", @" '$(Configuration)' == '' ");
            writer.WriteValue("DebugBuild");
            writer.WriteEndElement();

            writer.WriteStartElement("Platform");
            writer.WriteAttributeString("Condition", @" '$(Platform)' == '' ");
            writer.WriteValue("AnyCPU");
            writer.WriteEndElement();

            writer.WriteStartElement("ProductVersion");
            if (SolutionBuilder.SolutionVersionType == SolutionVersionTypeEnum.VS2005)
            {
                writer.WriteValue("8.0.50727");
            }
            else
            {
                writer.WriteValue("9.0.21022");
            }
            writer.WriteEndElement();

            writer.WriteStartElement("SchemaVersion");
            writer.WriteValue("2.0");
            writer.WriteEndElement();

            writer.WriteStartElement("ProjectGuid");
            writer.WriteValue(ProjectGuid);
            writer.WriteEndElement();

            writer.WriteStartElement("OutputType");
            writer.WriteValue("Library");
            writer.WriteEndElement();

            // added to support workflow templates by TPattison on 4/29/2008
            if (!string.IsNullOrEmpty(SolutionBuilder.ProjectTypeGuids))
            {
                writer.WriteStartElement("AppDesignerFolder");
                writer.WriteValue("Properties");
                writer.WriteEndElement();
            }
            // end addition on 4/29/2008 


            writer.WriteStartElement("RootNamespace");
            writer.WriteValue(ProjectName);
            writer.WriteEndElement();

            if (SolutionBuilder.SolutionVersionType == SolutionVersionTypeEnum.VS2008_30)
            {
                writer.WriteStartElement("TargetFrameworkVersion");
                writer.WriteValue("v3.0");
                writer.WriteEndElement();
            }

            if (SolutionBuilder.SolutionVersionType == SolutionVersionTypeEnum.VS2008_35)
            {
                writer.WriteStartElement("TargetFrameworkVersion");
                writer.WriteValue("v3.5");
                writer.WriteEndElement();
            }

            if (SolutionBuilder.AssemblyDeployment)
            {
                writer.WriteStartElement("SignAssembly");
                writer.WriteValue("true");
                writer.WriteEndElement();
                writer.WriteStartElement("AssemblyOriginatorKeyFile");
                string FilePath = SolutionBuilder.KeyFileName;
                writer.WriteValue(FilePath);
                writer.WriteEndElement();
            }
            else
            {
                writer.WriteStartElement("SignAssembly");
                writer.WriteValue("false");
                writer.WriteEndElement();
            }

            if (!string.IsNullOrEmpty(SolutionBuilder.ProjectTypeGuids))
            {
                writer.WriteStartElement("ProjectTypeGuids");
                writer.WriteValue(SolutionBuilder.ProjectTypeGuids);
                writer.WriteEndElement();
            }

            writer.WriteEndElement(); // </PropertyGroup>

            // <PropertyGroup> DebugBuild </PropertyGroup>
            writer.WriteStartElement("PropertyGroup");
            writer.WriteAttributeString("Condition", @" '$(Configuration)|$(Platform)' == 'DebugBuild|AnyCPU' ");

            writer.WriteStartElement("DebugSymbols");
            writer.WriteValue(true);
            writer.WriteEndElement();

            writer.WriteStartElement("DebugType");
            writer.WriteValue("full");
            writer.WriteEndElement();

            writer.WriteStartElement("Optimize");
            writer.WriteValue(false);
            writer.WriteEndElement();

            writer.WriteStartElement("OutputPath");
            writer.WriteValue(@"bin\Debug\");
            writer.WriteEndElement();

            writer.WriteStartElement("DefineConstants");
            writer.WriteValue("DEBUG;TRACE");
            writer.WriteEndElement();

            writer.WriteStartElement("ErrorReport");
            writer.WriteValue("prompt");
            writer.WriteEndElement();

            writer.WriteStartElement("WarningLevel");
            writer.WriteValue("4");
            writer.WriteEndElement();

            writer.WriteEndElement(); // </PropertyGroup>

            // Add <PropertyGroup> element for each configuation
            foreach (string Configuration in SolutionBuilder.Configurations)
            {
                writer.WriteStartElement("PropertyGroup");
                writer.WriteAttributeString("Condition", @" '$(Configuration)|$(Platform)' == '" + Configuration + "|AnyCPU' ");
                if (Configuration.Contains("Release"))
                {
                    writer.WriteStartElement("OutputPath");
                    writer.WriteValue(@"bin\Release\");
                    writer.WriteEndElement();
                    writer.WriteStartElement("DebugType");
                    writer.WriteValue("pdbonly");
                    writer.WriteEndElement();
                    writer.WriteStartElement("Optimize");
                    writer.WriteValue("true");
                    writer.WriteEndElement();
                    writer.WriteStartElement("DefineConstants");
                    writer.WriteValue("TRACE");
                    writer.WriteEndElement();
                    writer.WriteStartElement("ErrorReport");
                    writer.WriteValue("prompt");
                    writer.WriteEndElement();
                    writer.WriteStartElement("WarningLevel");
                    writer.WriteValue("4");
                    writer.WriteEndElement();
                }
                else
                {
                    writer.WriteStartElement("OutputPath");
                    writer.WriteValue(@"bin\Debug\");
                    writer.WriteEndElement();
                    writer.WriteStartElement("DefineConstants");
                    writer.WriteValue("DEBUG;TRACE");
                    writer.WriteEndElement();
                }
                writer.WriteEndElement(); // </PropertyGroup>
            }

            // <ItemGroup> references
            writer.WriteStartElement("ItemGroup");

            // Add <Reference> element for each assembly to be referenced in solution project
            foreach (string ProjectAssemblyReference in SolutionBuilder.ProjectAssemblyReferences)
            {
                writer.WriteStartElement("Reference");
                writer.WriteAttributeString("Include", ProjectAssemblyReference);
                writer.WriteEndElement();
            }

            writer.WriteEndElement(); // </ItemGroup>

            // <ItemGroup> folder
            writer.WriteStartElement("ItemGroup");
            foreach (string Folder in Folders)
            {
                writer.WriteStartElement("Folder");
                writer.WriteAttributeString("Include", Folder);
                writer.WriteEndElement();
            }
            writer.WriteEndElement(); // </ItemGroup>

            // <ItemGroup> source files
            writer.WriteStartElement("ItemGroup");
            foreach (SourceFile sourceFile in SourceFiles)
            {
                writer.WriteStartElement(sourceFile.Type.ToString());
                writer.WriteAttributeString("Include", sourceFile.FileName);
                // Added 3/18/08 by TPattison to support desiner components
                if (sourceFile.IsComponent)
                {
                    writer.WriteStartElement("SubType");
                    writer.WriteValue("Component");
                    writer.WriteEndElement();  //</SubType>
                }
                // Added 3/18/08 by TPattison to support desiner components
                if (!string.IsNullOrEmpty(sourceFile.DepedencyFileName))
                {
                    writer.WriteStartElement("DependentUpon");
                    writer.WriteValue(sourceFile.DepedencyFileName);
                    writer.WriteEndElement();  //</DependentUpon>
                }

                //Added 2/7/08 DMANN to support CustomTool attribute
                if (!string.IsNullOrEmpty(sourceFile.CustomTool))
                {
                    writer.WriteStartElement("SubType");
                    writer.WriteValue("Designer");
                    writer.WriteEndElement();  //</SubType>
                    writer.WriteStartElement("Generator");
                    writer.WriteValue(sourceFile.CustomTool);
                    writer.WriteEndElement();  //</Generator>

                }
                //End of 2/7/08 add
                writer.WriteEndElement();
            }

            // added to support workflow templates by TPattison on 4/29/2008
            if (!string.IsNullOrEmpty(SolutionBuilder.ProjectTypeGuids))
            {
                writer.WriteStartElement("AppDesigner");
                writer.WriteAttributeString("Include", @"Properties\");
                writer.WriteEndElement();
            }
            // end addition for 4/29/2008

            writer.WriteEndElement(); // </ItemGroup>

            writer.WriteStartElement("Import");
            writer.WriteAttributeString("Project", @"$(MSBuildBinPath)\Microsoft.CSharp.targets");
            writer.WriteEndElement(); // </Import>

            // added to support workflow templates by TPattison on 4/29/2008
            if (!string.IsNullOrEmpty(SolutionBuilder.ProjectTypeGuids))
            {
                writer.WriteStartElement("Import");
                writer.WriteAttributeString("Project", @"$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.0\Workflow.Targets");
                writer.WriteEndElement(); // </Import>
            }
            // end addition for 4/29/2008

            if (File.Exists(Globals.TargetsFilePath))
            {

                // <Import Project="DeploymentFiles\Microsoft.SharePoint.targets" />
                writer.WriteStartElement("Import");
                writer.WriteAttributeString("Project", Globals.TargetsFilePath);
                writer.WriteEndElement(); // </Import>

                writer.WriteStartElement("Target");
                writer.WriteAttributeString("Name", "AfterBuild");

                // Add <CallTarget> element for each configuation
                foreach (string Configuration in SolutionBuilder.Configurations)
                {
                    writer.WriteStartElement("CallTarget");
                    writer.WriteAttributeString("Targets", Configuration);
                    writer.WriteAttributeString("Condition", " '$(Configuration)|$(Platform)' == '" + Configuration + "|AnyCPU' ");
                    writer.WriteEndElement(); // </CallTarget>
                }
                writer.WriteEndElement(); // </Target>
            }

            writer.WriteEndElement(); // </Project>

            writer.WriteEndDocument();
            writer.Close();
            manifestStream.Close();
        }
    }
}
